#include<iostream>
#include <queue>
#include <string>
#include <mutex>
#include <condition_variable>
#include <thread>
#include <fstream>
#include <atomic>
#include <sstream>
#include <vector>
#include <stdexcept>


// 辅助函数，将单个参数转换为字符串
template<typename T>
std::string to_string_helper(T&& arg);

// 线程安全的日志队列
class LogQueue {
public:
    void push(const std::string& msg);

    bool pop(std::string& msg);

    void shutdown();

private:
    std::queue<std::string> queue_;
    std::mutex mutex_;
    std::condition_variable cond_var_;
    bool is_shutdown_ = false;
};

// Logger 类
class Logger {
public:
    Logger(const std::string& filename) : log_file_(filename, std::ios::out | std::ios::app), exit_flag_(false) {
        if (!log_file_.is_open()) {
            throw std::runtime_error("无法打开日志文件");
        }
        worker_thread_ = std::thread(&Logger::processQueue, this);
    }

    ~Logger() {
        log_queue_.shutdown();
        if (worker_thread_.joinable()) {
            worker_thread_.join();
        }
        if (log_file_.is_open()) {
            log_file_.close();
        }
    }

    // 日志接口：支持带格式字符串的日志
    template<typename... Args>
    void log(const std::string& format, Args&&... args) {
        log_queue_.push(formatMessage(format, std::forward<Args>(args)...));
    }


private:
    LogQueue log_queue_;
    std::thread worker_thread_;
    std::ofstream log_file_;
    std::atomic<bool> exit_flag_;

    void processQueue();

    // 使用模板折叠格式化日志消息，支持 "{}" 占位符
    template<typename... Args>
    std::string formatMessage(const std::string& format, Args&&... args) {
        std::vector<std::string> arg_strings = { to_string_helper(std::forward<Args>(args))... };
        std::ostringstream oss;
        size_t arg_index = 0;
        size_t pos = 0;
        size_t placeholder = format.find("{}", pos);

        while (placeholder != std::string::npos) {
            oss << format.substr(pos, placeholder - pos);
            if (arg_index < arg_strings.size()) {
                oss << arg_strings[arg_index++];
            } else {
                // 没有足够的参数，保留 "{}"
                oss << "{}";
            }
            pos = placeholder + 2; // 跳过 "{}"
            placeholder = format.find("{}", pos);
        }

        // 添加剩余的字符串
        oss << format.substr(pos);

        // 如果还有剩余的参数，按原方式拼接
        while (arg_index < arg_strings.size()) {
            oss << arg_strings[arg_index++];
        }

        return oss.str();
    }
};
